#ifndef UNIAST_RUNTIME_LOGGER_H
#define UNIAST_RUNTIME_LOGGER_H

#include <ctime>
#include <fstream>
#include <iostream>
#include <mutex>
#include <sstream>
#include <string>

namespace UniAST
{

class Logger
{
  public:
    enum LogLevel
    {
        DEBUG,
        INFO,
        WARN,
        ERROR
    };

    // 获取单例实例
    static Logger &getLogger(LogLevel level = INFO,
                             const std::string &logFile = "");

    // 删除拷贝构造和赋值运算符，确保唯一性
    Logger(const Logger &) = delete;
    Logger &operator=(const Logger &) = delete;

    // 设置日志级别
    void setLogLevel(LogLevel level);

    // use stream operator `<<` to log
    template <typename T> Logger &operator<<(const T &message)
    {
        if (this->streamLogLevel < currentLogLevel)
            return *this; // 过滤低于当前等级的日志
        std::lock_guard<std::mutex> lock(mtx);

        std::ostringstream oss;
        oss << message;

        std::string messageStr = oss.str();
        if (outFile.is_open())
        {
            outFile << messageStr;
        }
        else
        {
            std::cout << messageStr;
        }
        return *this;
    }

    // 允许指定日志级别
    template <typename T> Logger &log(LogLevel level, const T &message)
    {
        this->streamLogLevel = level;
        if (level < currentLogLevel)
            return *this; // 过滤低于当前等级的日志

        std::lock_guard<std::mutex> lock(mtx);

        std::ostringstream oss;
        oss << message;

        std::string messageStr = oss.str();
        logMessage(level, messageStr);

        return *this;
    }

  private:
    LogLevel currentLogLevel;
    LogLevel streamLogLevel;
    std::ofstream outFile;
    std::mutex mtx; // 确保线程安全

    Logger(LogLevel level = INFO, const std::string &logFile = "");

    ~Logger();

    void logMessage(LogLevel level, const std::string &message);

    std::string logLevelToString(LogLevel level);

    std::string getCurrentTime();
};

} // namespace UniAST

#ifndef LOGGER
#define LOGGER Logger::getLogger()
#endif

#endif